"""Сравнение модели со следующим экспериментом:
https://www.jstage.jst.go.jp/article/tstj/7/ists26/7_ists26_Pb_71/_pdf

В будущем можно проверить другой вариант: Nitrogen + water mixture
https://www.sciencedirect.com/science/article/pii/S030193222030584X#bib0005
"""

from math import pi

import numpy as np
import pytest

import cstpu
from cstpu import determine_valve_output

g = 9.80665  # m/sec**2

NOZZLE_THROAT_DIAMETER = 0.4e-3  # m
NOZZLE_OUTLET_DIAMETER = 6e-3  # m

# Use 1088 K maximum temperature, not 300 K of pipe inlet
CHAMBER_TEMPERATURE = 1088  # K
CHAMBER_PRESSURE = 0.68  # bar

EXPERIMENT_THRUST = 16.6e-3  # N
EXPERIMENT_IMP_SP = 203 * g  # m/sec
EXPERIMENT_MASS_FLOW = 0.5e-3 / 60  # kg/sec

# Подменяем значения в модуле, значениями из эксперимента
cstpu.F_KR_0 = pi * NOZZLE_THROAT_DIAMETER**2 / 4  # nozzle throat area, m^2
cstpu.FE_NOZZLE_0 = pi * NOZZLE_OUTLET_DIAMETER**2 / 4  # nozzle exit area, m^2

# Предполагаемые к-ты потерь
cstpu.PHI_C = 0.99
cstpu.PHI_N = 0.99


MAX_RELATIVE_ERROR = 0.05  # Допустимое отклонение от эксперимента 5%

thrust, imp_sp, mass_flow = cstpu.calculate_flow_from_nozzle(
    CHAMBER_PRESSURE, CHAMBER_TEMPERATURE
)

nozzle_flow_test_data = [
    pytest.param(thrust, EXPERIMENT_THRUST, id="thrust close to experiment"),
    pytest.param(imp_sp, EXPERIMENT_IMP_SP, id="impulse close to experiment"),
    pytest.param(mass_flow, EXPERIMENT_MASS_FLOW, id="mass flow close to experiment"),
]

determine_valve_output_test_data = [
    pytest.param([100, 100, 1], [100, 100], id="Opened"),
    pytest.param([100, 100, 0], [0, 0], id="Closed"),
]

limit_to_range_test_data = [
    pytest.param(cstpu.limit_to_range(1, 2, 5), 2, id="Out of range on the left"),
    pytest.param(cstpu.limit_to_range(6, 2, 5), 5, id="Out of range on the right"),
    pytest.param(cstpu.limit_to_range(3, 2, 5), 3, id="Inside the range"),
    pytest.param(cstpu.limit_to_range(2, 2, 5), 2, id="Coincides with the left border"),
    pytest.param(
        cstpu.limit_to_range(5, 2, 5), 5, id="Coincides with the right border"
    ),
]


@pytest.mark.parametrize("calculated_value, experiment_value", nozzle_flow_test_data)
def test_calculate_flow_from_nozzle(calculated_value, experiment_value):
    assert calculated_value == pytest.approx(experiment_value, rel=MAX_RELATIVE_ERROR)


@pytest.mark.parametrize(
    "input_data, expected_output_data", determine_valve_output_test_data
)
def test_determine_valve_output(input_data, expected_output_data):
    assert (determine_valve_output(*input_data) == np.array(expected_output_data)).all()


@pytest.mark.parametrize("value, expected_value", limit_to_range_test_data)
def test_limit_to_range(value, expected_value):
    assert value == expected_value
